-- TransferStateMachine.vhd 
-- Group DoDaRobo
-- EECS 452 Winter 2009
-- Module interfacing the MemMan and McBSPXmtr2 modules
-- Goal: read the memory buffer containing image frames
--       and send the data to the McBSP modeule, which
--       sends it to the DSK. Deal with timing and control
--       issues
-- by Phil, Adrian, Anna, Esther, Fred
-- Last modified : 3/28/2009
-- Last change : Written
-- INSERT ANY ADDITIONAL CHANGES HERE!

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity TransferStateMachine is
    Port (	  -- memory manager control signals:
				  req_get_memman : out STD_LOGIC;
				  ack_get_memman : in STD_LOGIC;
				  get_address_memman : out STD_LOGIC_VECTOR(17 downto 0);
				  get_data_memman : in STD_LOGIC_VECTOR (15 downto 0);
				  
				  -- mbscp control signals:
				  write_data_tomcbsp : out STD_LOGIC_VECTOR (15 downto 0);
				  rcv_data_frommbscp : in STD_LOGIC_VECTOR (15 downto 0);
				  rdy_mcbsp : out STD_LOGIC;
				  ack_mcbsp : in STD_LOGIC;
				  
				  SN : out std_logic_vector(5 downto 0);
				  Anna : out std_logic_vector(15 downto 0);
				  
				  clk : in STD_LOGIC);				  				 						  
end TransferStateMachine;


architecture Behavioral of TransferStateMachine is

-- SIGNALS HERE

type t_state is (SendFF, A, B, C, D);
signal state, next_state : t_state := SendFF;
signal address : std_logic_vector (17 downto 0);
signal verCounter, horCounter : std_logic_vector (15 downto 0);
signal dataToSend : std_logic_vector (15 downto 0);
signal endOfAddress : std_logic;
signal counter : std_logic_vector (15 downto 0);
signal mcbspCounter : std_logic_vector (15 downto 0);

begin
   
	Anna <= mcbspCounter;
	
   update : process(clk)
   begin
      if rising_edge(clk) then
         state <= next_state;
         -- FILL IN EVERYTHING HERE.
			-- MAYBE NOTHING.
		end if;
		
   end process;
     
   statemachine : process(clk)
   begin
   	
		if rising_edge(clk) then
		
		if ack_mcbsp = '1' then
			mcbspCounter <= mcbspCounter + '1';
		end if;
		
      case state is
		
         when SendFF =>
			   dataToSend <= X"FFFF";
				req_get_memman <= '0';
				rdy_mcbsp <= '1';
				address <= "000000000000000000";
				--address <= conv_std_logic_vector(288*320,address'length);
				
				SN <= "000001";
				
				if ack_mcbsp = '0' then
					next_state <= SendFF;
				elsif ack_mcbsp = '1' then
					next_state <= A;
				end if;
				
				
         when A =>
				req_get_memman <= '1';
				rdy_mcbsp <= '0';	
					
				if ack_get_memman = '0' then
					next_state <= A;
				elsif ack_get_memman = '1' and ack_mcbsp = '0' then
					next_state <= B;
				end if;
				--state_num(7 downto 4) <= X"1";
				
				SN <= "000010";
				

         when B =>
				dataToSend <= get_data_memman;
			
				req_get_memman <= '1';
				rdy_mcbsp <= '1';
			
				SN <= "000100";
				-- here, write the data we want to send to mcbsp
				-- from the data we got from the memory manager

					
				if ack_mcbsp = '0' then
					next_state <= B;
				elsif ack_mcbsp = '1' then
					next_state <= C;
				end if;
			

			when C =>
				req_get_memman <= '0';
				rdy_mcbsp <= '0';
				counter <= counter + '1';
				
				if counter = 32 then
					--if ack_mcbsp = '0' then
					--	next_state <= D;
					--elsif ack_mcbsp = '1' then
					--	next_state <= C;
					--end if;
					
					next_state <= D;
					counter <= X"0000";
				else
					next_state <= C;
				end if;
			
				SN <= "001000";
			
			when D =>
				req_get_memman <= '0';
				rdy_mcbsp <= '0';	
	
				-- avoid multiplication
				-- address <= verCounter * 640 + horCounter;
				
				-- Code to incrememnt address:
				-- 640 * 292 - (640 - 355) = 186595
				

--			if verCounter = 291 and horCounter = 354 then WE ARE SUSPICIOUS!!!

				if verCounter = 287 and horCounter = 174 then
					endOfAddress <= '1';
					horCounter <= horCounter + '1';
					address <= address + '1';
					
				--elsif verCounter = 291 and horCounter = 355 then
				elsif verCounter = 287 and horCounter = 175 then
					verCounter <= X"0001";
					horCounter <= X"0000";
					address <= "000000000000000000";
					
					
				--elsif horCounter = 355 then
				elsif horCounter = 175 then
					verCounter <= verCounter + '1';
					horCounter <= X"0000";
					address <= address + 145;
				else
					horCounter <= horCounter + '1';
					address <= address + '1';
				end if;

--				if verCounter = 0 and horCounter = 1 then
--					endOfAddress <= '1';
--					address <= address - 1;
--					
--				elsif verCounter = 0 and horCounter = 0 then
--					verCounter <= conv_std_logic_vector(287,verCounter'length);
--					horCounter <= conv_std_logic_vector(319,horCounter'length);
--					address <= conv_std_logic_vector(288*320,address'length);
--					
--				elsif horCounter = 0 then
--					verCounter <= verCounter - 1;
--					horCounter <= conv_std_logic_vector(319,horCounter'length);
--					address <= address - 320;
--				else
--					horCounter <= horCounter - 1;
--					address <= address - 1;
--				end if;
				
				if endOfAddress = '0' then
					next_state <= A;
				elsif endOfAddress = '1' then
					next_state <= SendFF;
					endOfAddress <= '0';
				end if;

				SN <= "010000";
				
      end case;
  
		end if;
  
   end process;

	-- anything else will go here 
	

	get_address_memman <= address;
	write_data_tomcbsp <= dataToSend;	
				  
end Behavioral;